// System_UnitTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

class TestClassA
{
public:
	int x;
	float height;
};

class TestClassB : public TestClassA
{
};

void TestWithoutInitialization()
{
	using namespace MOE::System::NonIntrusive;

	assert(TokenClassMetaManager::SingletonInitialized() == false);
	assert(ClassMeta<int>().IsNil() == true);
	assert(ClassMeta<float>().IsNil() == true);
	assert(ClassMeta<TestClassA>().IsNil() == true);
	assert(ClassMeta<TestClassB>().IsNil() == true);
}

void TestBaseCase()
{
	using namespace MOE::System::NonIntrusive;

	TokenClassMetaManager::InitializeSingleton();

	assert(TokenClassMetaManager::SingletonInitialized() == true);

	// Make sure base types are registered immediately.
	assert(ClassMeta<int>().IsNil() == false);
	assert(ClassMeta<float>().IsNil() == false);

	// Make sure classes are not registered before we initialize.
	assert(ClassMeta<TestClassA>().IsNil() == true);

	{
		MOE::Core::ClassMeta* pMeta = InitializeType<TestClassA>::As("TestClassA", sizeof(TestClassA));
		assert(pMeta != nullptr);

		pMeta->AddField(new MOE::Core::Field(*pMeta, "x", MOE::Core::Type(ClassMeta<int>()), offsetof(TestClassA, x)));
		pMeta->AddField(new MOE::Core::Field(*pMeta, "height", MOE::Core::Type(ClassMeta<float>()), offsetof(TestClassA, height)));

		assert(pMeta->GetField("x").IsValid());
		assert(pMeta->GetField("x").GetType().GetTypeSize() == sizeof(MOE::Core::int32));
		assert(pMeta->GetField("height").IsValid());
		assert(pMeta->GetField("height").GetType().GetTypeSize() == sizeof(MOE::Core::float32));
	}

	// Now I'm registered!
	const MOE::Core::ClassMeta& classAMeta = ClassMeta<TestClassA>();
	assert(classAMeta.IsNil() == false);

	TestClassA objOfA;
	classAMeta.GetField("x").WriteValue(MOE::Core::CRef(1), MOE::Core::Ref(objOfA));
	assert(objOfA.x == 1);

	int xOut = 0;
	classAMeta.GetField("x").ReadValue(MOE::Core::CRef(objOfA), MOE::Core::Ref(xOut));
	assert(xOut == 1);

	TokenClassMetaManager::ReleaseSingleton();
}

void TestDestroyAndReinitialize()
{
	using namespace MOE::System::NonIntrusive;

	TokenClassMetaManager::InitializeSingleton();

	// Do test 1.

	TokenClassMetaManager::ReleaseSingleton();

	assert(TokenClassMetaManager::SingletonInitialized() == false);

	TokenClassMetaManager::InitializeSingleton();

	// Do test 2.

	TokenClassMetaManager::ReleaseSingleton();

	assert(TokenClassMetaManager::SingletonInitialized() == false);
}

int _tmain(int argc, _TCHAR* argv[])
{
	TestWithoutInitialization();
	TestBaseCase();
	TestDestroyAndReinitialize();

	return 0;
}

